import ast

from 程序核心代码.ast节点.节点定义.ast节点结构创建.ast节点结构创建 import 创建赋值节点, 创建二元操作节点
from 程序核心代码.ast节点.节点定义.具体ast节点.操作类.值操作类.操作类节点模版 import 双目操作类ast节点基础模型, 操作类节点图形
from 程序核心代码.ast节点.节点定义.基础定义.ast节点基础定义 import ast节点基础模型
from 程序核心代码.mvvm重构.基础定义.基础图形项.基础图形组件.子组件.下拉列表 import 下拉列表组件
from 程序核心代码.mvvm重构.基础定义.节点管理器.自动节点注册表 import 注册节点模型, 节点模型匹配器


@注册节点模型(ast.AugAssign)
class 增强赋值ast节点基础模型(ast节点基础模型):
    """
    处理 ast.AugAssign 节点的赋值语句节点类。
    """

    def 节点数据解析(self):
        pass

    #先拆解   a+=b  为 a=b+a
    def __init__(self,ast节点, 所属节点模型管理器, 上级节点=None, 节点位置=None):
        super().__init__(ast节点, 所属节点模型管理器,  "增强赋值",上级节点=上级节点, 节点位置=节点位置)
        self.拆解节点()
    def 拆解节点(self):
        值内容 = self._ast节点.value
        #获取赋值目标
        赋值目标 = self._ast节点.target
        self.操作类型 = self._ast节点.op

        # 删除当前节点 创建新的节点重新解析
        双目运算节点=创建二元操作节点(赋值目标,self.操作类型 , 值内容)
        新的赋值节点 = 创建赋值节点(赋值目标, 双目运算节点)
        self.ast节点 = 新的赋值节点
        # print("替换后")
        # print(ast.dump(起始接口.所属节点模型管理器.ast操作器.获取节点(起始接口.节点路径), annotate_fields=True, indent=4))

        节点模型匹配器(self.ast节点, self.所属节点模型管理器)
        #起始接口.所属节点模型管理器.ast操作器.插入节点(起始接口.节点路径[:-1], 新的赋值节点,起始接口.节点路径[-1]+1)
        #二元操作节点(起始接口.节点路径, 起始接口.所属节点模型管理器)

@注册节点模型(ast.BinOp)
class 二元操作节点(双目操作类ast节点基础模型):
    """
    处理 ast.AugAssign 节点的赋值语句节点类。
    """
    def 节点数据解析(self):
        self.参数名称="操作类型"
        self.参数值=self._ast节点.op

    def __init__(self,ast节点, 所属节点模型管理器, 上级节点=None, 节点位置=None):
        super().__init__(ast节点, 所属节点模型管理器,  "二元运算",上级节点=上级节点,节点位置=节点位置)

    def 初始化操作类型映射(self):
        self.操作类型映射 = {
            # 算术运算符
            "相加": [ast.Add(), "+"],
            "相减": [ast.Sub(), "-"],
            "相乘": [ast.Mult(), "*"],
            "相除": [ast.Div(), "/"],
            "取余": [ast.Mod(), "%"],
            "幂": [ast.Pow(), "**"],
            "取整除": [ast.FloorDiv(), "//"],
            # 按位运算符
            "按位与": [ast.BitAnd(), "&"],
            "按位或": [ast.BitOr(), "|"],
            "按位异或": [ast.BitXor(), "^"],
            "按位左移": [ast.LShift(), "<<"],
            "按位右移": [ast.RShift(), ">>"],
            "按位取反": [ast.Invert(), "~"],

        }

    def 获取输入值与输出值(self):
        self.输入值节点1 = 节点模型匹配器(self._ast节点.left, self.所属节点模型管理器, 上级节点=self)
        self.输入值节点2 = 节点模型匹配器(self._ast节点.right, self.所属节点模型管理器, 上级节点=self)

@注册节点模型(ast.BoolOp)
class 布尔运算节点(双目操作类ast节点基础模型):
    """
    处理 ast.AugAssign 节点的赋值语句节点类。
    """

    def 节点数据解析(self):
        self.参数名称="操作类型"
        self.参数值 = self._ast节点.op

    #单目操作

    def __init__(self,ast节点, 所属节点模型管理器, 上级节点=None, 节点位置=None):
        super().__init__(ast节点, 所属节点模型管理器, "布尔运算",上级节点=上级节点,节点位置=节点位置)
    def 初始化操作类型映射(self):
        self.操作类型映射 = {
            # 算术运算符
            "逻辑与": [ast.And(), "and"],
            "逻辑或": [ast.Or(), "or"],
        }
    def 获取输入值与输出值(self):
        if  len(self._ast节点.values)<2:
            print(ast.dump(self._ast节点, annotate_fields=True, indent=4))
            raise ValueError("布尔运算节点必须至少两个输入值")
        输入值列表=[]
        for 输入值 in self._ast节点.values:
            输入值列表.append(节点模型匹配器(输入值, self.所属节点模型管理器, 上级节点=self))
@注册节点模型(ast.UnaryOp)
class 单目运算节点(双目操作类ast节点基础模型):
    """
    处理 ast.AugAssign 节点的赋值语句节点类。
    """

    def 节点数据解析(self):
        self.参数名称="操作类型"
        self.参数值 = self._ast节点.op

    #单目操作

    def __init__(self,ast节点, 所属节点模型管理器, 上级节点=None, 节点位置=None):
        super().__init__(ast节点, 所属节点模型管理器, "单目运算",上级节点=上级节点,节点位置=节点位置)
    def 初始化操作类型映射(self):
        self.操作类型映射 = {
            # 一元运算符
            "正号": [ast.UAdd(), "+"],
            "负号": [ast.USub(), "-"],
            "布尔值取反": [ast.Not(), "not"],
            "按位取反": [ast.Invert(), "~"],
        }
    def 获取输入值与输出值(self):
        self.输入值节点 = 节点模型匹配器(self._ast节点.operand, self.所属节点模型管理器, 上级节点=self)
    def 处理关系(self):
        if self.输入值节点:
            起始接口 = self.添加接口到节点("数据流", "输入", 必须连接=True)
            结束接口 = self.输入值节点.添加接口到节点("数据流", "输出", 必须连接=True)
            起始接口.接口创建连接线模型(结束接口, self)

@注册节点模型(ast.Compare)
class 多值比较ast节点基础模型(ast节点基础模型):
    """
    处理 ast.AnnAssign 节点的赋值语句节点类。
    """

    def 节点数据解析(self):
        self.参数名称="aaa"
        self.参数值 = "aaa"

    def __init__(self,ast节点, 所属节点模型管理器,上级节点=None, 节点位置=None):
        super().__init__(ast节点, 所属节点模型管理器,  "值比较", 上级节点=上级节点,节点位置=节点位置)
        """
        1 <= a < 10
        Expr(
            value=Compare(
                left=Constant(value=1),
                ops=[
                    LtE(),
                    Lt()],
                comparators=[
                    Name(id='a', ctx=Load()),
                    Constant(value=10)]))],
        """
        self.初始化操作类型映射()
        self.图形项 = 操作类节点图形(self)
        self.初始化操作类型映射()
        第一个比较参数节点 = 节点模型匹配器(self._ast节点.left, self.所属节点模型管理器, 上级节点=self)
        #起始接口.添加接口到节点("数据流", "输入", 接口名称="对比值", 必须连接=True)
        结束接口 = self.添加接口到节点("数据流", "输入", 接口名称="对比值0", 必须连接=True)
        起始接口 = 第一个比较参数节点.添加接口到节点("数据流", "输出", 必须连接=True)
        起始接口.接口创建连接线模型(结束接口, self)
        self.操作符组件列表= []
        索引=0
        for 操作符, 参数 in zip(self._ast节点.ops, self._ast节点.comparators):
            下拉列表2=下拉列表组件(list(self.操作类型映射.keys()), self.操作类型修改, 标识=索引)
            self.输入区域.append(下拉列表2)
            下拉列表2.下拉组件.更改当前选中(self.获取键通过_ast_结构(操作符))
            self.操作符组件列表.append(下拉列表2)
            当前参数节点=节点模型匹配器(参数, self.所属节点模型管理器, 上级节点=self)
            结束接口 = self.添加接口到节点("数据流", "输入", 接口名称="对比值"+str(索引+1), 必须连接=True)
            起始接口 = 当前参数节点.添加接口到节点("数据流", "输出", 必须连接=True)
            起始接口.接口创建连接线模型(结束接口, self)
            索引 +=1


    def 初始化操作类型映射(self):
        self.操作类型映射 = {
            # 算术运算符
            # 比较运算符
            "小于": [ast.Lt(), "<"],
            "小于等于": [ast.LtE(), "<="],
            "大于": [ast.Gt(), ">"],
            "大于等于": [ast.GtE(), ">="],
            "等于": [ast.Eq(), "=="],
            "不等于": [ast.NotEq(), "!="],
            "is": [ast.Is(), "is"],
            "is not": [ast.IsNot(), "is not"],
            "in": [ast.In(), "in"],
            "not in": [ast.NotIn(), "not in"],

        }

    def 操作类型修改(self, 操作类型, 标识):
        """
        更新操作类型并同步到AST节点。
        """
        if 操作类型 in self.操作类型映射:
            self.操作类型 = 操作类型
            self._ast节点.ops[标识] = self.操作类型映射.get(操作类型, [None, None])[0]
            print(f"操作类型已修改为: {self.操作类型}")
        else:
            print(f"无效的操作类型: {操作类型}")

        # 更新图形项显示
        self.操作符组件列表[标识].下拉组件.更改当前选中(self.操作类型)
    def 获取键通过_ast_结构(self,ast_结构):
        #print("获取键通过_ast_结构",ast_结构)
        for 键, 值 in self.操作类型映射.items():
            if isinstance(ast_结构, type(值[0])):
                return 键
        raise Exception("错误ast_结构",ast_结构)